---
title: エンドポイント
description: どんな種類のデータでも提供できるエンドポイントの作成方法について学びます。
i18nReady: true
---
import RecipeLinks from "~/components/RecipeLinks.astro";

Astroでは、どんな種類のデータでも提供できるカスタムエンドポイントを作成できます。これを利用して、画像を生成したり、RSSを公開したり、またはAPIルーティングとして使用してサイトの完全なAPIを構築したりできます。

静的に生成されたサイトでは、カスタムエンドポイントは静的ファイルを生成するため、ビルド時に呼び出されます。[SSR](/ja/guides/server-side-rendering/)モードを選択した場合、カスタムエンドポイントはリクエストに応じて呼び出される動的なサーバーエンドポイントに変わります。静的エンドポイントとSSRエンドポイントは同じ様に定義されますが、SSRエンドポイントは追加機能をサポートします。


## 静的ファイルのエンドポイント

カスタムエンドポイントを作成するには、`.js`または`.ts`ファイルを`/pages`ディレクトリに追加してください。`.js`または`.ts`の拡張子はビルドプロセス中に削除されるので、ファイル名には作成したいデータの拡張子を含める必要があります。たとえば、`src/pages/data.json.ts`は、ビルドすると`/data.json`エンドポイントとなります。

エンドポイントは、`Astro`グローバルと同様のプロパティを持つ[コンテキストオブジェクト](/ja/reference/api-reference/#endpoint-context)を受け取る`GET`関数（`async`も可）をエクスポートします。以下のエンドポイントは`name`と`url`を持つレスポンスオブジェクトを返しており、Astroはビルド時にこれを呼び出し、bodyの内容を使ってファイルを生成します。

```ts
// 例: src/pages/builtwith.json.ts
// 出力: /builtwith.json
export async function GET({params, request}) {
  return new Response(
    JSON.stringify({
      name: 'Astro',
      url: 'https://astro.build/'
    })
  )
}
```

Astro v3.0以降、返り値の`Response`オブジェクトが`encoding`プロパティを含む必要はなくなりました。たとえば、バイナリのpng画像を生成する場合は次のようになります。

```ts title="src/pages/astro-logo.png.ts" {3}
export async function GET({ params, request }) {
  const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
  return new Response(await response.arrayBuffer());
}
```

また、`APIRoute`型を使用してエンドポイント関数に型付けもできます。

```ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ params, request }) => {...}
```

### `params`と動的ルーティング

エンドポイントは、ページと同じ[動的ルーティング](/ja/guides/routing/#%E5%8B%95%E7%9A%84%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)機能をサポートしています。ファイル名を角括弧付きのパラメーター名とし、[`getStaticPaths()`関数](/ja/reference/api-reference/#getstaticpaths)をエクスポートしてください。そして、エンドポイント関数に渡された`params`プロパティを使用して、パラメーターにアクセスします。


```ts title="src/pages/api/[id].json.ts"
import type { APIRoute } from 'astro';

const usernames = ["Sarah", "Chris", "Yan", "Elian"]

export const GET: APIRoute = ({ params, request }) => {
  const id = params.id;
  return new Response(
    JSON.stringify({
      name: usernames[id]
    })
  )
}

export function getStaticPaths() {
  return [ 
    { params: { id: "0"} },
    { params: { id: "1"} },
    { params: { id: "2"} },
    { params: { id: "3"} }
  ]
}
```

これにより、ビルド時に`/api/0.json`、`/api/1.json`、`/api/2.json`、`/api/3.json`という4つのJSONエンドポイントが生成されます。エンドポイントによる動的ルーティングはページと同じように動作しますが、エンドポイントはコンポーネントではなく関数であるため、[props](/ja/reference/api-reference/#data-passing-with-props)はサポートされていません。

### `request`

すべてのエンドポイントは`request`プロパティを受け取りますが、静的モードでは`request.url`にのみアクセスが可能です。これは、現在のエンドポイントの完全なURLを返し、[Astro.request.url](/ja/reference/api-reference/#astrorequest)がページに対して行うのと同じように動作します。

```ts title="src/pages/request-path.json.ts"
import type { APIRoute } from 'astro';

export const GET: APIRoute = ({ params, request }) => {
  return new Response(JSON.stringify({
      path: new URL(request.url).pathname
    })
  )
}
```


## サーバーエンドポイント（APIルーティング）

静的ファイルエンドポイントのセクションで説明したものはすべて、SSRモードでも使用できます。ファイルは、`Astro`グローバルと同様のプロパティを持つ[コンテキストオブジェクト](/ja/reference/api-reference/#endpoint-context)を受け取る`GET`関数をエクスポートできます。

しかし、`static`モードとは異なり、`server`モードを設定すると、エンドポイントはリクエストされた時点でビルドされます。これにより、ビルド時には利用できない新しい機能が利用可能となり、リクエストをリッスンするAPIルートを構築したり、実行時にサーバー上で安全にコードを実行できるようになります。

<RecipeLinks slugs={["ja/recipes/call-endpoints" ]}/>

:::note
これらの例を試す前に、必ず[SSRを有効](/ja/guides/server-side-rendering/)にしてください。
:::

サーバーエンドポイントは、`getStaticPaths`のエクスポートなしで`params`にアクセスできます。また、[`Response`](https://developer.mozilla.org/ja/docs/Web/API/Response)オブジェクトを返せるので、ステータスコードやヘッダーを設定できます。


```js title="src/pages/[id].json.js"
import { getProduct } from '../db';

export async function GET({ params }) {
  const id = params.id;
  const product = await getProduct(id);

  if (!product) {
    return new Response(null, {
      status: 404,
      statusText: 'Not found'
    });
  }

  return new Response(
    JSON.stringify(product), {
      status: 200,
      headers: {
        "Content-Type": "application/json"
      }
    }
  );
}
```

これは、動的ルーティングにマッチするすべてのリクエストに応答します。たとえば、`/helmet.json`に移動した場合、`params.id`は`helmet`に設定されます。モックの商品データベースに`helmet`が存在すれば、エンドポイントは`Response`オブジェクトを作成してJSONで応答し、成功を意味する[HTTPステータスコード](https://developer.mozilla.org/ja/docs/Web/API/Response/status)を返します。存在しない場合は、`Response`オブジェクトを使用して`404`で応答します。

特定のプロバイダーは、SSRモードで画像を返すために`Content-Type`ヘッダーを要求します。この場合、`Response`オブジェクトを使用して`headers`プロパティを指定します。以下はバイナリの`.png`画像を返却する例です。
```ts title="src/pages/astro-logo.png.ts"
export async function GET({ params, request }) {
  const response = await fetch("https://docs.astro.build/assets/full-logo-light.png");
  const buffer = Buffer.from(await response.arrayBuffer());
  return new Response(buffer, {
    headers: { "Content-Type": "image/png" },
  });
}
```

### HTTPメソッド

`GET`関数に加えて、任意の[HTTPメソッド](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods)の名前をもつ関数をエクスポートできます。リクエストが来た時、Astroはメソッドをチェックし、対応する関数を呼び出します。

対応するエクスポートされた関数がないHTTPメソッドにマッチする`ALL`関数をエクスポートすることもできます。対応するメソッドがないリクエストが来た場合、サイトの[404ページ](/ja/basics/astro-pages/#カスタム404エラーページ)にリダイレクトされます。

```ts title="src/pages/methods.json.ts"
export const GET: APIRoute = ({ params, request }) => {
  return new Response(JSON.stringify({
      message: "This was a GET!"
    })
  )
}

export const POST: APIRoute = ({ request }) => {
  return new Response(JSON.stringify({
      message: "This was a POST!"
    })
  )
}

export const DELETE: APIRoute = ({ request }) => {
  return new Response(JSON.stringify({
      message: "This was a DELETE!"
    })
  )
}

export const ALL: APIRoute = ({ request }) => {
  return new Response(JSON.stringify({
      message: `This was a ${request.method}!`
    })
  )
}
```

<RecipeLinks slugs={["ja/recipes/captcha", "ja/recipes/build-forms-api" ]}/>

### `request` 

SSRモードでは、`request`プロパティは、現在のリクエストを参照する完全に使用可能な[`Request`](https://developer.mozilla.org/ja/docs/Web/API/Request)オブジェクトを返します。これにより、データの取得やヘッダーのチェックができます。

```ts title="src/pages/test-post.json.ts"
export const POST: APIRoute = async ({ request }) => {
  if (request.headers.get("Content-Type") === "application/json") {
    const body = await request.json();
    const name = body.name;
    return new Response(JSON.stringify({
      message: "名前: " + name
    }), {
      status: 200
    })
  }
  return new Response(null, { status: 400 });
}
```

### リダイレクト

エンドポイントのコンテキストは、`Astro.redirect`に似た`redirect()`ユーティリティをエクスポートします。

```js title="src/pages/links/[id].js" {14}
import { getLinkUrl } from '../db';

export async function GET({ params, redirect }) {
  const { id } = params;
  const link = await getLinkUrl(id);

  if (!link) {
    return new Response(null, {
      status: 404,
      statusText: 'Not found'
    });
  }

  return redirect(link, 307);
}
```
